// Copyright (c) 2020 InCore Semiconductors Pvt. Ltd. see LICENSE.incore for more details on licensing terms
/*
Author: Neel Gala, neelgala@incoresemi.com
Created on: Friday 01 May 2020 05:19:08 PM IST

*/
package Soc_instances ;

import FIFOF        :: * ;
import Vector       :: * ;
import SpecialFIFOs :: * ;
import FIFOF        :: * ;
`include "Logger.bsv"
`include "Soc_map.bsv"

import uart         :: * ;
import bootconfig   :: * ;
import clint        :: * ;
import plic         :: * ;
import gpio         :: * ;
import pwm          :: * ;
import spi          :: * ;
import rom          :: * ;
import ram1rw       :: * ;
import riscv_debug  :: * ;
import debug_loop   :: * ;
import bridges      :: * ;
import axi4         :: * ;
import axi4l        :: * ;
import apb          :: * ;
import qspi         :: * ;

(*synthesize*)
module mkdebug_loop(Ifc_debug_loop_apb#(`paddr, 32, `User));
	let clk <-exposeCurrentClock;
	let reset <-exposeCurrentReset;
  let ifc();
  mkdebug_loop_apb#(`DebugBase, clk, reset) _temp(ifc);
  return ifc;
endmodule:mkdebug_loop
(*synthesize*)
module mkbootrom(Ifc_rom_apb#(`paddr, 32, `User, 1024, 32, 1));
	let clk <-exposeCurrentClock;
	let reset <-exposeCurrentReset;
  let ifc();
  mk_rom_apb#(`ROMBase, replicate("boot.mem")) _temp(ifc);
  return ifc;
endmodule:mkbootrom
(*synthesize*)
module mkuart0(Ifc_uart_apb#(`paddr, 32, `User, 16));
	let clk <-exposeCurrentClock;
	let reset <-exposeCurrentReset;
  let ifc();
  mkuart_apb#(`ifdef simulate 5 `else 27 `endif , `Uart0Base, clk, reset) _temp(ifc);
  return ifc;
endmodule:mkuart0
(*synthesize*)
module mkgpio(Ifc_gpio_apb#(`paddr, 32, `User, 22,`gpio_interrupt_size));
  let clk <- exposeCurrentClock;
  let rst <- exposeCurrentReset;
  let ifc();
  mkgpio_apb#(`GPIOBase, clk, rst) _temp(ifc);
  return ifc;
endmodule:mkgpio
(*synthesize*)
module mkpwm(Ifc_pwm_apb#(`paddr, 32, `User, `pwmwidth, `channels, `comp_out_en));
  let clk <- exposeCurrentClock;
  let rst <- exposeCurrentReset;
  let ifc();
  mkpwm_apb#(`PWMBase, clk, rst) _temp(ifc);
  return ifc;
endmodule:mkpwm

(*synthesize*)
module mkclint(Ifc_clint_axi4l#(`paddr, 32, `User, 256, 1));
	let clk <-exposeCurrentClock;
	let reset <-exposeCurrentReset;
  let ifc();
  mkclint_axi4l#(`ClintBase, clk, reset) _temp(ifc);
  return ifc;
endmodule:mkclint
(*synthesize*)
module mkplic(Ifc_plic_axi4l#(`paddr, 32, `User, 32, 1, 3));
  let clk <- exposeCurrentClock;
  let rst <- exposeCurrentReset;
  let ifc();
  mkplic_axi4l#(`PLICBase, clk, rst) _temp(ifc);
  return ifc;
endmodule:mkplic
(*synthesize*)
module mkocm(Ifc_ram1rw_axi4l#(`paddr, 32, `User, 4096, 32, 1));
	let clk <-exposeCurrentClock;
	let reset <-exposeCurrentReset;
  let ifc();
  mk_ram1rw_axi4l#(`OCMBase, replicate("ocm.mem"), "nc") _temp(ifc);
  return ifc;
endmodule:mkocm
(*synthesize*)
module mkbootconfig(Ifc_bootconfig_apb#(`paddr, 32, `User, 2));
	let clk <-exposeCurrentClock;
	let reset <-exposeCurrentReset;
  let ifc();
  mkbootconfig_apb#(`BootconfigBase, clk, reset) _temp(ifc);
  return ifc;
endmodule:mkbootconfig

(*synthesize*)
module mkqspi(Ifc_qspi_apb#(`paddr, 32, `User, `AXI4ID, `paddr, 64, `User));
  let clk <- exposeCurrentClock;
  let reset <- exposeCurrentReset;
  let ifc();
	mkqspi_apb#(`QSPICfgBase, clk,reset) _temp(ifc);
  return ifc;
endmodule:mkqspi


// ------- Fabric instances
//----------------------- AXI4 Crossbar
typedef Ifc_axi4_fabric #(`AXI4_Masters, `AXI4_Slaves, `AXI4ID, `paddr, 64, `User)  Fabric_AXI4_IFC;

function Bit#(TMax#(TLog#(`AXI4_Slaves),1)) fn_axi4_rd_map(Bit#(`paddr) paddr);
  if (paddr >= `APBBridgeBase && paddr <= `APBBridgeEnd) return `APBBridge_slave_num;
  else if (paddr >= `AXI4LBridgeBase && paddr <= `AXI4LBridgeEnd) return `AXI4LBridge_slave_num;
  else if (paddr >= `DDRBase       && paddr <= `DDREnd)       return `DDR_slave_num;
  else if (paddr >= `OpenBase      && paddr <= `OpenEnd)      return `Open_slave_num;
  else if (paddr >= `QSPIMemBase && paddr <= `QSPIMemEnd) return `QSPI_mem_slave_num;
  else return `AXI4Err_slave_num;
endfunction:fn_axi4_rd_map

function Bit#(TMax#(TLog#(`AXI4_Slaves),1)) fn_axi4_wr_map(Bit#(`paddr) paddr);
  if (paddr >= `APBBridgeBase && paddr <= `APBBridgeEnd) return `APBBridge_slave_num;
  else if (paddr >= `AXI4LBridgeBase && paddr <= `AXI4LBridgeEnd) return `AXI4LBridge_slave_num;
  else if (paddr >= `DDRBase       && paddr <= `DDREnd)       return `DDR_slave_num;
  else if (paddr >= `OpenBase      && paddr <= `OpenEnd)      return `Open_slave_num;
  else return `AXI4Err_slave_num;
endfunction:fn_axi4_wr_map

(*synthesize*)
module mkaxi4_crossbar (Fabric_AXI4_IFC);
  Fabric_AXI4_IFC fabric <- mkaxi4_fabric_2 (fn_axi4_rd_map, fn_axi4_wr_map, '1, '1, '1, '1);
  return fabric;
endmodule:mkaxi4_crossbar

//------------------------- AXI4Lite Crossbar
function Bit#(TMax#(TLog#(`AXI4L_Slaves),1)) fn_axi4l_rd_map(Bit#(`paddr) paddr);
  if      (paddr >= `ClintBase && paddr <= `ClintEnd ) return `Clint_slave_num;
  else if (paddr >= `PLICBase  && paddr <= `PLICEnd )  return `Plic_slave_num;
  else if (paddr >= `OCMBase   && paddr <= `OCMEnd )   return `Ocm_slave_num;
  else return `AXI4LErr_slave_num;
endfunction:fn_axi4l_rd_map

function Bit#(TMax#(TLog#(`AXI4L_Slaves),1)) fn_axi4l_wr_map(Bit#(`paddr) paddr);
  if      (paddr >= `ClintBase && paddr <= `ClintEnd ) return `Clint_slave_num;
  else if (paddr >= `PLICBase  && paddr <= `PLICEnd )  return `Plic_slave_num;
  else if (paddr >= `OCMBase   && paddr <= `OCMEnd )   return `Ocm_slave_num;
  else return `AXI4LErr_slave_num;
endfunction:fn_axi4l_wr_map

typedef Ifc_axi4l_fabric #(`AXI4L_Masters, `AXI4L_Slaves, `paddr, 32, `User)  Fabric_AXI4L_IFC;

(*synthesize*)
module mkaxi4l_crossbar (Fabric_AXI4L_IFC);
  Fabric_AXI4L_IFC fabric <- mkaxi4l_fabric_2 (fn_axi4l_rd_map, fn_axi4l_wr_map, '1, '1, '1, '1);
  return fabric;
endmodule:mkaxi4l_crossbar

// ------------------------ APB
function Bit#(TMax#(TLog#(`APB_Slaves),1)) fn_apb_addr_map(Bit#(`paddr) paddr);
  if      (paddr >= `DebugBase      && paddr <= `DebugEnd ) return `Debug_slave_num;
  else if (paddr >= `ROMBase        && paddr <= `ROMEnd   ) return `Rom_slave_num;
  else if (paddr >= `Uart0Base      && paddr <= `Uart0End ) return `Uart0_slave_num;
  else if (paddr >= `BootconfigBase && paddr <= `BootconfigEnd )    return `Bootconfig_slave_num;
  else if (paddr >= `GPIOBase       && paddr <= `GPIOEnd  ) return `Gpio_slave_num;
  else if (paddr >= `PWMBase        && paddr <= `PWMEnd   ) return `Pwm_slave_num;
  else if (paddr >= `SPIClusterBase && paddr <= `SPIClusterEnd )    return `SPICluster_slave_num;
  else if (paddr >= `QSPICfgBase && paddr <= `QSPICfgEnd) return `QSPI_cfg_slave_num;
  else return `ApbErr_slave_num;
endfunction:fn_apb_addr_map

(*synthesize, clock_prefix="PCLK", reset_prefix="PRESETN"*)
module mkapb_interconnect(Ifc_apb_fabric#(`paddr, 32, `User,  `APB_Slaves ));
  let ifc();
  mkapb_fabric #(fn_apb_addr_map) _temp(ifc);
  return (ifc);
endmodule:mkapb_interconnect

// -------------- Bridges
(*synthesize*)
module mkaxi2apb_bridge(Ifc_axi2apb#(`AXI4ID, `paddr, 64, `paddr, 32, `User));
  let ifc();
  mkaxi2apb _temp(ifc);
  return ifc();
endmodule:mkaxi2apb_bridge

(*synthesize*)
module mkaxi2axil_bridge(Ifc_axi2axil#(`AXI4ID, `paddr, 64, `paddr, 32, `User));
  let ifc();
  mkaxi2axil _temp(ifc);
  return ifc();
endmodule:mkaxi2axil_bridge

endpackage: Soc_instances

